package org.arclib.draw;

import org.arclib.Texture;
import org.arclib.math.Common;
import org.arclib.math.Point;
import org.arclib.math.Size;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;

/**
 * 
 * @author Clay Smith
 * 
 */
public class Draw
{
	// / draw pixel at position and color
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawPixel(org.arclib.math.Point,
	 * org.arclib.draw.Color)
	 */
	public static void pixel(Point pos, Color color)
	{
		// disable gl textures
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// make sure the line width is only 1 pixel wide
		GL11.glLineWidth(1);

		// draw line
		GL11.glBegin(GL11.GL_LINE_LOOP);

		GL11.glVertex2d(pos.getX(), pos.getY());
		GL11.glVertex2d(pos.getX() + 1, pos.getY());

		GL11.glEnd();
	}

	// / draw line with color
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawLine(org.arclib.math.Point,
	 * org.arclib.math.Point, org.arclib.draw.Color)
	 */
	public static void line(Point pos1, Point pos2, Color color)
	{
		// disable gl textures
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// draw line
		GL11.glBegin(GL11.GL_LINE_LOOP);

		GL11.glVertex2d(pos1.getX(), pos1.getY());
		GL11.glVertex2d(pos2.getX(), pos2.getY());

		GL11.glEnd();
	}

	// / draw circle at position, size (radius), detail (vertex's), and color
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawCircle(org.arclib.math.Point, float,
	 * int, org.arclib.draw.Color, boolean)
	 */
	public static void circle(Point pos, double radius, int detail,
			Color color, boolean fill)
	{
		// primitives can only be drawn once textures are disabled
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// we will be drawing lines
		if (fill)
		{
			GL11.glBegin(GL11.GL_POLYGON);
		} else
		{
			GL11.glBegin(GL11.GL_LINE_LOOP);
		}

		double px;
		double py;

		for (float i = 0; i < 360; i += 360.0 / detail)
		{
			// create polar coordinate
			px = radius;
			py = i;

			// translate it to rectangular
			py = Common.degreesToRadians(py); // convert degrees to radian

			double x_save = px;

			px = x_save * Math.cos(py); // i know, polar->y is used too much,
										// but i'd like to eliminate the need
			py = x_save * Math.sin(py); // for too many variables

			// and draw it
			GL11.glVertex2d(pos.getX() + px, pos.getY() + py);
		}

		GL11.glEnd();
	}

	// / draw rectange with given position, size, and color
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawRectangle(org.arclib.math.Point,
	 * org.arclib.math.Size, org.arclib.draw.Color, boolean)
	 */
	public static void rectangle(Point pos, Size size, Color color, boolean fill)
	{
		// disable images
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// draw a box line of border
		if (fill == true)
		{
			GL11.glBegin(GL11.GL_POLYGON);
		} else
		{
			GL11.glBegin(GL11.GL_LINE_LOOP);
			// make sure the line width is only 1 pixel wide
			GL11.glLineWidth(1);
		}

		// draw box to the screen
		GL11.glVertex2d(pos.getX() + size.getW(), pos.getY());

		GL11.glVertex2d(pos.getX() + size.getW(), pos.getY() + size.getH());

		GL11.glVertex2d(pos.getX(), pos.getY() + size.getH());

		GL11.glVertex2d(pos.getX(), pos.getY());

		GL11.glEnd();
	}

	// / draw rectange with given position, size, and color
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawRoundEdgeRect(org.arclib.math.Point,
	 * org.arclib.math.Size, int, org.arclib.draw.Color, boolean)
	 */
	public static void roundEdgeRect(Point pos, Size size, int detail,
			Color color, boolean fill)
	{
		// disable images
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// draw a box line of border
		if (fill == true)
		{
			GL11.glBegin(GL11.GL_POLYGON);
		} else
		{
			GL11.glBegin(GL11.GL_LINE_LOOP);
			// make sure the line width is only 1 pixel wide
			GL11.glLineWidth(1);
		}

		// mult detail by 4
		detail *= 4;

		double px, py;

		Point start = new Point(pos.getX() + (size.getH() / 2), pos.getY()
				+ (size.getH() / 2));

		// first draw from 90-->180
		for (double i = 90; i <= 270; i += 360.0 / detail)
		{
			// create polar coordinate
			px = size.getH() / 2;
			py = i;

			// translate it to rectangular
			py = Common.degreesToRadians(py); // convert degrees to radian

			double x_save = px;

			px = x_save * Math.cos(py); // i know, polar->y is used too much,
										// but i'd like to eliminate the need
			py = x_save * Math.sin(py); // for too many variables

			// and draw it
			GL11.glVertex2d(start.getX() + px, start.getY() + py);
		}

		// draw from top left --> right left
		GL11.glVertex2d(pos.getX() + (size.getH() / 2), pos.getY());
		GL11.glVertex2d(pos.getX() + size.getW() - (size.getH() / 2), pos
				.getY());

		start = new Point(pos.getX() + size.getW() - (size.getH() / 2), pos
				.getY()
				+ (size.getH() / 2));

		// first draw from 270-->360
		for (float i = 270; i <= 360; i += 360.0 / detail)
		{
			// create polar coordinate
			px = size.getH() / 2;
			py = i;

			// translate it to rectangular
			py = Common.degreesToRadians(py); // convert degrees to radian

			double x_save = px;

			px = x_save * Math.cos(py); // i know, polar->y is used too much,
										// but i'd like to eliminate the need
			py = x_save * Math.sin(py); // for too many variables

			// and draw it
			GL11.glVertex2d(start.getX() + px, start.getY() + py);
		}

		// first draw from 270-->360
		for (double i = 0; i <= 90; i += 360.0 / detail)
		{
			// create polar coordinate
			px = size.getH() / 2;
			py = i;

			// translate it to rectangular
			py = Common.degreesToRadians(py); // convert degrees to radian

			double x_save = px;

			px = x_save * Math.cos(py); // i know, polar->y is used too much,
										// but i'd like to eliminate the need
			py = x_save * Math.sin(py); // for too many variables

			// and draw it
			GL11.glVertex2d(start.getX() + px, start.getY() + py);
		}

		// next draw top left corner
		GL11.glEnd();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.arclib.draw.IRender#drawPolygon(java.util.ArrayList,
	 * org.arclib.draw.Color, boolean)
	 */
	public static void polygon(ArrayList<Point> polygon, Color color,
			boolean fill)
	{
		// disable images
		GL11.glDisable(GL11.GL_TEXTURE_2D);

		// set color to one given
		color.setGLColor();

		// draw a box line of border
		if (fill == true)
		{
			GL11.glBegin(GL11.GL_POLYGON);
		} else
		{
			GL11.glBegin(GL11.GL_LINE_LOOP);
			GL11.glLineWidth(1);
		}

		for (int i = 0; i < polygon.size(); i++)
		{
			GL11.glVertex2d(polygon.get(i).getX(), polygon.get(i).getY());
		}

		GL11.glEnd();
	}

	// / simply draw image to screen with given image ID from the center with
	// pivot points
	public static void image(Texture argTexture, Point argPos, Size argSize,
			Point argPivot, double argAngle, Color argColor)
	{
		if (argSize.w == 0 && argSize.h == 0)
		{
			argSize = argTexture.getImageSize();
		}

		// center calculations
		double halfWidth = argSize.halfW();
		double halfHeight = argSize.halfH();

		double texw = (argTexture.getImageSize().getW() / argTexture.getSize()
				.getW());
		double texh = (argTexture.getImageSize().getH() / argTexture.getSize()
				.getH());

		// enable 2d textures and bind texture
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		// bind texture ID to this tex
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, argTexture.getID());

		// set color to one given
		argColor.setGLColor();

		GL11.glPushMatrix();

		// rotate and translate
		GL11.glTranslated(argPos.getX(), argPos.getY(), 0);
		GL11.glRotatef((float) Common.radiansToDegrees(argAngle), 0, 0, 1);

		// draw image at given coordinates, binding texture appropriately
		GL11.glBegin(GL11.GL_QUADS);

		// -halfWidth and -halfHeight act as anchors to rotate from the center
		GL11.glTexCoord2d(0, texh);
		GL11.glVertex2d(-halfWidth + argPivot.getX(), -halfHeight
				+ argPivot.getY());

		GL11.glTexCoord2d(0, 0);
		GL11.glVertex2d(-halfWidth + argPivot.getX(), -halfHeight
				+ argSize.getH() + argPivot.getY());

		GL11.glTexCoord2d(texw, 0);
		GL11.glVertex2d(-halfWidth + argSize.getW() + argPivot.getX(),
				-halfHeight + argSize.getH() + argPivot.getY());

		GL11.glTexCoord2d(texw, texh);
		GL11.glVertex2d(-halfWidth + argSize.getW() + argPivot.getX(),
				-halfHeight + argPivot.getY());

		GL11.glEnd();

		GL11.glPopMatrix();
	}

	// / draw image from the top left location
	public static void imageBottomLeft(Texture argTexture, Point argPos,
			Size argSize, Color argColor)
	{
		// enable 2d textures and bind texture
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		// bind texture ID to this tex
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, argTexture.getID());

		// set color to one given
		argColor.setGLColor();

		GL11.glPushMatrix();

		// rotate and translate
		GL11.glTranslated(argPos.getX(), argPos.getY(), 0);

		double texw = argTexture.getImageSize().getW()
				/ argTexture.getSize().getW();
		double texh = argTexture.getImageSize().getH()
				/ argTexture.getSize().getH();

		// draw image at given coordinates, binding texture appropriately
		GL11.glBegin(GL11.GL_QUADS);

		// -halfWidth and -halfHeight act as anchors to rotate from the center
		GL11.glTexCoord2d(0, texh);
		GL11.glVertex2f(0, 0);

		GL11.glTexCoord2d(0, 0);
		GL11.glVertex2d(0, argSize.getH());

		GL11.glTexCoord2d(texw, 0);
		GL11.glVertex2d(argSize.getW(), argSize.getH());

		GL11.glTexCoord2d(texw, texh);
		GL11.glVertex2d(argSize.getW(), 0);

		GL11.glEnd();

		GL11.glPopMatrix();
	}

	// / draw a subsection of an image with the top-left at 0,0
	public static void imageSubsection(Texture argTexture, Point argPos,
			Point argTopLeft, Point argRightBottom, Color argColor)
	{
		// enable 2d textures and bind texture
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		// bind texture ID to this texture
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, argTexture.getID());

		// set color
		argColor.setGLColor();

		GL11.glPushMatrix();
		GL11.glTranslated(argPos.getX(), argPos.getY(), 0);

		// draw image at given coordinates, binding texture appropriately
		GL11.glBegin(GL11.GL_QUADS);

		double width = argTexture.getSize().getW();
		double height = argTexture.getSize().getH();

		double tLeft = argTopLeft.getX() / width, tTop = argTopLeft.getY()
				/ height, tRight = argRightBottom.getX() / width, tBottom = argRightBottom
				.getY()
				/ height;

		GL11.glTexCoord2d(tLeft, tBottom);
		GL11.glVertex2f(0, 0);

		GL11.glTexCoord2d(tLeft, tTop);
		GL11.glVertex2d(0, argRightBottom.getY() - argTopLeft.getY());

		GL11.glTexCoord2d(tRight, tTop);
		GL11.glVertex2d(argRightBottom.getX() - argTopLeft.getX(),
				argRightBottom.getY() - argTopLeft.getY());

		GL11.glTexCoord2d(tRight, tBottom);
		GL11.glVertex2d(argRightBottom.getX() - argTopLeft.getY(), 0);

		GL11.glEnd();

		GL11.glPopMatrix();
	}

}
